/**
 * 链表栈
 * 尾插法，实现得不够丝滑
 * 采用头插法比较好
 */
export class Node {
  public data: any;
  public next: Node | null;
  constructor(data: any) {
    this.data = data;
    this.next = null;
  }
}

/** 链表栈 */
export default class LinkedStack {
  private stackLength: number;
  private ele_number: number;
  private stackHead: Node;
  constructor(n: number) {
    this.stackLength = n;

    this.stackHead = new Node('');
    this.ele_number = 0;
  }

  /** 入栈 */
  public push(value: any) {
    if (this.ele_number == this.stackLength) {
      console.log('入栈失败，已满');
      return false;
    }

    this.ele_number++;
    this.append(value);
  }

  /** 出栈 */
  public pop() {
    if (this.ele_number == 0) {
      console.log('出栈失败，已空');
      return false;
    }
    this.ele_number--;
    this.rmLast();
  }

  public print() {
    let current = this.stackHead;
    while (current) {
      console.log(current.data);
      current = current.next;
    }
  }

  private append(value: any) {
    let current = this.stackHead;

    // 检查是否存在下一个节点
    while (current.next) {
      current = current.next;
    }

    current.next = new Node(value);
  }

  /** 移除链表最后一个节点 */
  private rmLast() {
    let current = this.stackHead;
    let nextNode = current.next;

    while (nextNode && nextNode.next) {
      current = nextNode;
      nextNode = nextNode.next;
    }

    current.next = null;
  }
}

const linkedStack = new LinkedStack(5);
linkedStack.push('h');
linkedStack.push('e');
linkedStack.push('l');
linkedStack.push('l');
linkedStack.push('o');
linkedStack.push('!');

linkedStack.print();

linkedStack.pop();
linkedStack.pop();
linkedStack.pop();

linkedStack.print();
